﻿// ----------------------------------------------------------------------
// <author name="Moses Kehengu"/>
// <copyright file="Program.cs" company="Futures Group International">
//     Copyright statement. All right reserved
// </copyright>
//
// ------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using GenericTools;
using System.Xml;
using System.IO;
using System.Configuration;
using ReportingManagement.Properties;
using System.Text;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data;
using DataModels.Enumerations;
using DataModels.Common;
using System.ComponentModel;
using GenericTools.CustomReporting;
using GenericTools.OfflineDataCapture;
using GenericTools.Models;

namespace ReportingManagement
{
    static class Program
    {
        private const string WEB_SERVICES_ADDRESS_FOR_DEBUGGING = "http://localhost:2014/IQService.asmx";

        private static string SETTINGS_VALUES_MAGIC = "201403061106qwertyuiop[]";
        private static void CreateCacheSettingsFileIfNotExists()
        {
            string cacheSettingsFile = @"C:\IQSMS\Cache\CacheSettings.mdb";
            if (File.Exists(cacheSettingsFile))
            {
                // Check if the file is compatible with this version.
                string magicText = Properties.Settings.Default.SETTINGS_VALUES_VERSION;
                if (magicText != SETTINGS_VALUES_MAGIC)
                {
#if DEBUG
                    string filename = Path.GetFileNameWithoutExtension(cacheSettingsFile);
                    string extension = Path.GetExtension(cacheSettingsFile);
                    string location = Path.GetDirectoryName(cacheSettingsFile);
                    Guid guid = Guid.NewGuid();
                    string newFilename = string.Format("{0}.{1}{2}", filename, guid.ToString(), extension);
                    string backupFilename = Path.Combine(location, newFilename);
                    
                    File.Move(cacheSettingsFile, backupFilename);       //Renaming the file instead of deleting it.
                    ExtractRecentSettingsFile(cacheSettingsFile);
#else
                    File.Delete(cacheSettingsFile);
                    ExtractRecentSettingsFile(cacheSettingsFile);
#endif
                }
            }
            else
            {
                ExtractRecentSettingsFile(cacheSettingsFile);
            }
        }

        private static void TryToCreateEmptyCacheDB()
        {
            var backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            backgroundWorker.RunWorkerAsync();
        }

        static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                StringBuilder sBuilder = new StringBuilder();
                sBuilder.Append(string.Format("Failed to create database: {0}", AppConfiguration.CacheDBName));
                Utilities.WriteLog(sBuilder.ToString());
                Utilities.LogError(e.Error, null);
            }
        }

        static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            SqlConnection connection = new SqlConnection(AppConfiguration.SQLCacheDBConnection);
            SqlCommand command = connection.CreateCommand();

            DbParameter param = null;
            command.Parameters.Clear();
            command.CommandText = "SELECT count(*) FROM master.dbo.sysdatabases WHERE name = @DatabaseName";
            param = command.CreateParameter();
            param.ParameterName = "@DatabaseName";
            param.DbType = DbType.String;
            param.Value = AppConfiguration.CacheDBName;
            command.Parameters.Add(param);
            string output = GenericDataAccess.ExecuteScalar(command, false);
            int count = Int32.Parse(output);
            if (count != 1)
            {
                command.CommandText = String.Format("CREATE DATABASE {0}", AppConfiguration.CacheDBName);
                command.ExecuteNonQuery();
                command.Connection.Close();

                StringBuilder sBuilder = new StringBuilder();
                sBuilder.Append(string.Format("Created cache database: {0}", AppConfiguration.CacheDBName));
                Utilities.WriteLog(sBuilder.ToString());
                e.Result = true;
            }
            else
            {
                e.Result = true;
            }
        }

        private static void ExtractRecentSettingsFile(string targetCacheSettingsFilename)
        {
            FileInfo compressedSourceCacheSettings = new FileInfo(targetCacheSettingsFilename + ".gz");
            string sourceCacheSettings = String.Format(@"{0}\Resources\CacheSettings.mdb.gz", Application.StartupPath);
            if (!Directory.Exists(compressedSourceCacheSettings.DirectoryName))
            {
                Directory.CreateDirectory(compressedSourceCacheSettings.DirectoryName);
            }

            File.Delete(compressedSourceCacheSettings.FullName);
            File.Copy(sourceCacheSettings, compressedSourceCacheSettings.FullName);

            DataTransformation.Decompress(compressedSourceCacheSettings);
            File.Delete(compressedSourceCacheSettings.FullName);

            Properties.Settings.Default.SETTINGS_VALUES_VERSION = SETTINGS_VALUES_MAGIC;
            Properties.Settings.Default.Save();
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                string cacheFile = Properties.Settings.Default.CacheFileName;
                string cacheSettingsFile = @"C:\IQSMS\Cache\CacheSettings.mdb";
                FileInfo cacheFileInfo = new FileInfo(cacheFile);
                FileInfo cacheSettingsFileInfo = new FileInfo(cacheSettingsFile);

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                string connectionName = "ReportingManagement.Properties.Settings.CacheDBConnection";
                AppConfiguration.CacheDBProviderName = ConfigurationManager.ConnectionStrings[connectionName].ProviderName;
                AppConfiguration.CacheDBConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;

                string sqlConnectionName = "ReportingManagement.Properties.Settings.SQLCacheDBConnection";
                AppConfiguration.SQLCacheDBConnection = ConfigurationManager.ConnectionStrings[sqlConnectionName].ConnectionString;
                //AppConfiguration.SSISPackageFilename = Settings.Default.SSISPackageFilename;
                AppConfiguration.CacheDBType = Settings.Default.TypeOfCacheDB;

                AppConfiguration.IsRunningDemo = Settings.Default.IsRunningDemo;
                
#if DEBUG
                AppConfiguration.WebServiceURL = WEB_SERVICES_ADDRESS_FOR_DEBUGGING;
#else
                AppConfiguration.WebServiceURL = Settings.Default.WebServiceURL;
#endif
                AppConfiguration.ApplicationName = Settings.Default.ApplicationName;
                AppConfiguration.EnableErrorLogMail = Settings.Default.EnableErrorLogMail;
                AppConfiguration.ErrorLogEmailAddress = Settings.Default.ErrorLogEmailAddress;
                AppConfiguration.LogFileDirectory = Settings.Default.LogFileDirectory;
                AppConfiguration.IQSMSBlog = Settings.Default.IQSMSBlog;
                AppConfiguration.DHISBaseUrl = Settings.Default.DHISBaseUrl;

                AppConfiguration.CacheDBName = Settings.Default.CacheDBName;
                TryToCreateEmptyCacheDB();
                AppConfiguration.SQLCacheDBConnection = AppConfiguration.SQLCacheDBConnection.Replace("master", AppConfiguration.CacheDBName);

                AppConfiguration.AccessMethod = Settings.Default.AccessMethod;
                if (AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS)
                {
                    AppConfiguration.DBConnectionString = AppConfiguration.SQLCacheDBConnection;
                    AppConfiguration.DBProviderName = AppConfiguration.DBProviderName;
                }
                
                //AppConfiguration.CacheDBConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;

                //string appDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                //string appCacheDBFolder = cacheFileInfo.DirectoryName;
                
                //System.IO.Directory.CreateDirectory(appCacheDBFolder);
                //if (!File.Exists(cacheFile))
                //{
                //    FileInfo compressedSourceCacheDB = new FileInfo(cacheFile + ".gz");
                //    string sourceCacheDB = String.Format(@"{0}\Resources\Cache.mdb.gz", Application.StartupPath);
                //    if (!Directory.Exists(compressedSourceCacheDB.DirectoryName))
                //    {
                //        Directory.CreateDirectory(compressedSourceCacheDB.DirectoryName);
                //    }
                //    File.Copy(sourceCacheDB, compressedSourceCacheDB.FullName);

                //    DataTransformation.Decompress(compressedSourceCacheDB);
                //    File.Delete(compressedSourceCacheDB.FullName);
                //}

                //if (!File.Exists(cacheSettingsFile))
                //{
                //    FileInfo compressedSourceCacheSettings = new FileInfo(cacheSettingsFile + ".gz");
                //    string sourceCacheSettings = String.Format(@"{0}\Resources\CacheSettings.mdb.gz", Application.StartupPath);
                //    if (!Directory.Exists(compressedSourceCacheSettings.DirectoryName))
                //    {
                //        Directory.CreateDirectory(compressedSourceCacheSettings.DirectoryName);
                //    }
                //    File.Copy(sourceCacheSettings, compressedSourceCacheSettings.FullName);

                //    DataTransformation.Decompress(compressedSourceCacheSettings);
                //    File.Delete(compressedSourceCacheSettings.FullName);
                //}     
                //string destinationCacheDB = String.Format(@"{0}\Cache.sdf", appCacheDBFolder);
                CreateCacheSettingsFileIfNotExists();
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    String.Format("There was an error on loading application configurations\n\nError Details\n{0}", 
                        ex.Message), "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            bool notClosed = true;
            try
            {
                do
                {
                    Login login = new Login();
                    DialogResult response = login.ShowDialog();
                    if (response == DialogResult.OK)
                    {
                        UserInformation authenticatedUser = login.AuthenticatedUser;
                        // Here we are setting the username and password hash, so that
                        // other classes that depends on it can use it.
                        string magicText = authenticatedUser.Username + "|" + authenticatedUser.Password;
                        string passwordHash = DataTransformation.Hash(magicText);

                        BaseWebAuthorization.Username = authenticatedUser.Username;
                        BaseWebAuthorization.PasswordHash = passwordHash;

                        AppConfiguration.DataCached = login.DataCached;

                        Loading pleaseWait = new Loading();
                        pleaseWait.Show();
                        Application.DoEvents();
                        MainWindow reportingManagement = new MainWindow(authenticatedUser);
                        pleaseWait.Close();
                        Application.Run(reportingManagement);
                        notClosed = reportingManagement.LoggedOff;
                    }
                    else break;
                } while (notClosed);
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("Error: " + ex.Message);
                sb.Append("\nSource: " + ex.Source);
                sb.Append("\nTarget Site: " + ex.TargetSite.Name);
                sb.Append("\nStack Trace:\n" + ex.StackTrace);
                if (ex.InnerException != null)
                {
                    sb.Append("\nInternal Exception: " + ex.InnerException.Message);
                    sb.Append("\nInternal Exception Source: " + ex.InnerException.Source);
                    sb.Append("\nInternal Exception Target Site: " + ex.InnerException.TargetSite.Name);
                    sb.Append("\nInternal Exception Stack Trace:\n" + ex.InnerException.StackTrace);
                }

                MessageBox.Show(sb.ToString());
                Utilities.WriteLog(sb.ToString());
                Utilities.LogError(ex, null);
            }
        }
    }
}
